package com.cskaoyan.javase.oop1._11static._0introduction._1new;

import java.util.Arrays;

/**
 * static关键字的引入
 * 引例：
 * 练习：
 * 	创建一个学生类，用来描述我们班全体同学，要求
 * 		属性：姓名，性别，年龄，学号，学校信息
 * 		行为：吃饭，学习
 *
 * 注：建议性别使用String类型的gender，不推荐使用布尔类型的isMale或者isFemale。
 *
 * 创建多个Student对象，他们的属性取值可以不同，会发现什么问题呢？
 *
 * 显然，我们会发现以下问题：
 *
 * 无论创建多少Student对象，由于该类描述的是我们班全体同学，他们的班级信息实际上是一样的
 * 创建多次对象，需要重复的给一个属性赋相同的值，这是很麻烦的，不方便的。
 * 学校信息这个属性实质上应该是被全体同学所共有的属性，而不是独属于某个对象的。
 * 所以，按照我们以往定义成员变量的方法来完成这个案例，是可以改进的。
 *
 *
 * 为了应对上述问题，我们需要改进我们的设计
 * 考虑如何改进？
 * 可以把成员变量schoolName中直接显式赋值为“王道训练营”或者直接写死构造方法
 * 这样确实可以实现功能，但是没有从根本上解决问题，问题3依然存在
 * 学校信息这个属性在每一个对象当中都存在，有点浪费内存空间
 * 最重要的，我们在设计类的时候其实已经知道这个属性，是全体对象都有，不应该属于某个对象。
 * 我们希望这个属性不是属于某一个对象的，而是一种类的特征，是属于类的，属于全体对象所共享的
 *
 * 上述改进不是我们最理想的改进方式，考虑以下改进：
 * 在内存中找一块区域，让该类的每个对象都共用这片区域，把SchoolName属性放进去
 * 于是：
 *
 * SchoolName从对象独有的成员变量变成全体对象所共享的一种变量
 * 这样做既节省空间，减少了初始化成员变量的时间损耗
 * 最重要的体现了该属性属于类，属于全体对象共享的特点
 * 实际上，属于全体对象所共享的变量在Java当中是存在的，它指的就是使用static关键字修饰的，Java当中的静态成员变量。
 *
 *
 * static关键字:
 *      static可以用来修饰成员变量,表示静态成员变量
 *      静态成员变量不是属于对象的,而是是属于全体对象所共享的,换句话说,它是属于类的
 *      语法:
 *      [访问权限修饰符] static 数据类型 变量名;
 *      静态成员变量属于类,所以禁止使用对象名点访问静态成员变量(虽然这样确实可以访问)
 *      应该使用类名点访问.
 *
 *      静态成员变量在赋值时,也可以使用显式赋值
 *      当然它和成员变量一样,都具有默认值,而且默认初始化是永远的第一步.各种类型的默认值和成员变量是一致的.
 *
 *      同样的static也可以用来修饰成员方法,这就是我们以前使用的方法,称之为静态成员方法.
 *      静态成员方法同样是属于类的,在调用时需要使用类名点调用,禁止使用对象名点调用.
 *      特殊的,如果是在同类中的static方法之间互相调用,可以省略类名,直接使用方法名调用.
 *      如果是跨类调用静态成员方法,是不可用省略类名的
 *      当然,也可以不论是否跨类,都使用类名点调用静态成员方法,这有助于提升代码可读性.
 *
 *      既然static修饰的静态成员(包括变量和方法)都是属于类的,那么请问:
 *              不创建对象能够使用它们吗?
 *              是完全可以的!!
 *              static修饰的静态成员的使用,完全不依赖于创建对象的过程.
 *              而是依赖于类加载的过程!!
 *
 * @since 11:13
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // WangDaoStudent s1 = new WangDaoStudent("张三", "男", 18, 1);
        // Static member 'com.cskaoyan.javase.oop1._11static._0introduction._1new.WangDaoStudent.schoolName' accessed via instance reference
        // 警告: 你正在通过一个对象引用访问静态成员变量,言下之意是,静态成员变量不应该用对象引用访问
        // 使用对象名点访问静态成员变量是错误的写法
        // System.out.println(s1.schoolName);
        // s1.schoolName = "友商训练营";
        System.out.println(WangDaoStudent.schoolName);
        WangDaoStudent.schoolName = "友商训练营";
        // WangDaoStudent s2 = new WangDaoStudent("李四", "女", 19, 2);
        // System.out.println(s2.schoolName);
        System.out.println(WangDaoStudent.schoolName);


        System.out.println("-----------------------");

        WangDaoStudent.test();
        test();

        // 包装类中parseXxx方法,是一个静态方法,有static修饰,这样才能够通过类名点调用
        Integer.parseInt("123");
    }

    // 静态成员方法
    public static void test(){
        System.out.println("我是Demo类的静态成员方法");
    }
}

class WangDaoStudent {
    String name;
    /*
        开发中,定义性别建议使用
        String gender
        不推荐使用布尔类型的isMale或者isFemale
        原因挖个坑,后面再说
     */
    String gender;
    int age;
    int id;
    static String schoolName = "王道训练营";

    public WangDaoStudent() {
    }

    public WangDaoStudent(String name, String gender, int age, int id) {
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.id = id;
    }

    public void eat() {
        System.out.println("饿了,我要吃饭");
    }

    public void study() {
        System.out.println("学习真快乐!");
    }

    // 静态成员方法
    public static void test(){
        System.out.println("我是WangDao学生类的静态成员方法");
    }
}